package api


type LuaType = int

type ArithOp = int 		//算术运算操作 类型别名

type CompareOp = int 	//比较操作 类型别名

type GoFunction func(LuaState) int  // Go函数类型


// Go闭包可以携带Upvalue这没问题, 问题时如何访问这些Upvalue呢？
// Lua API并没有提供专门的方法，而是想注册表那样，提供了伪索引
// 和Lua栈索引一样，Upvalue索引也是从1开始递增
// 对于任何一个Upvalue索引，用注册表伪索引减去该索引就可以得到对应的Upvalue伪索引
// 为了便于使用，把这个转换过程封装在LuaUpvalueIndex()函数里
func LuaUpvalueIndex(i int) int {

	return LUA_REGISTRYINDEX - i

}


// 扩展BasicAPI和AuxLib接口
type LuaState interface {
	BasicAPI

	AuxLib
}


type BasicAPI interface {

	/* basic stakc manipulation */

	GetTop() int

	AbsIndex(idx int) int

	CheckStack(n int) bool

	Pop(n int)

	Copy(fromIdx, toIdx int)

	PushValue(idx int)

	Replace(idx int)

	Insert(idx int)

	Remove(idx int)

	Rotate(idx, n int)

	SetTop(idx int)


	/* access functions(stack -> Go) */

	TypeName(tp LuaType) string

	Type(idx int) LuaType

	IsNone(idx int) bool

	IsNil(idx int) bool

	IsNoneOrNil(idx int) bool

	IsBoolean(idx int) bool

	IsInteger(idx int) bool

	IsNumber(idx int) bool

	IsString(idx int) bool

	IsFunction(idx int) bool

	ToBoolean(idx int) bool

	ToInteger(idx int) int64

	ToIntegerX(idx int) (int64, bool)

	ToNumber(idx int) float64

	ToNumberX(idx int) (float64, bool)

	ToString(idx int) string

	ToStringX(idx int) (string, bool)

	GetAddr(idx int) string

	/* push functions (Go -> stack) */

	PushNil()

	PushBoolean(b bool)

	PushInteger(n int64)

	PushNumber(n float64)

	PushString(s string)


	Arith(op ArithOp)	// 算术和按位运算

	Compare(idx1, idx2 int, op CompareOp) bool 	// 比较运算

	Len(idx int)	// 取长度运算

	Concat(n int)	// 字符串拼接运算

	/* get functions (Lua -> stack) */

	NewTable()

	CreateTable(nArr, nRec int)

	GetTable(idx int)	LuaType

	GetField(idx int, k string)	LuaType

	GetI(idx int, i int64)	LuaType

	/* set functions (stack -> Lua) */
	SetTable(idx int)

	SetField(idx int, k string)

	SetI(idx int, n int64) 

	// 加载二进制chunk, 把主函数原型实例化为闭包并推入栈顶
	// chunk: 字节数组, 给出要加载的chunk数据
	// chunkName: 指定chunk的名字, 供加载错误或调试时使用
	// mode: 加载模式, "b":必须是二进制chunk数据; "t":必须是文本chunk数据; "bt":可以是二进制或文本chunk数据
	// 返回一个状态码, 0表示加载成功, 非0表示加载失败
	Load(chunk []byte, chunkName, mode string) int

	// 对Lua函数进行调用
	// 在执行Call()方法之前必须先把被调函数推入栈顶, 然后把参数值依次推入栈顶
	// Call()方法结束之后, 参数值和函数会被弹出栈顶, 取而代之的是指定数量的返回值
	// nArgs: 指定准备传递给被调函数的参数数量, 同时也隐含给出了被调函数在栈里的位置
	// nResults: 指定需要的返回值数量(多退少补), 如果是-1, 则被调函数的返回值会全部留在栈顶
	Call(nArgs, nResults int)

	// 把Go函数转换成Go闭包并放入栈顶
	PushGoFunction(f GoFunction)

	// 判定索引处的值是否可以转换为Go函数
	IsGoFunction(idx int) bool

	// 把栈里的Go闭包再转换为Go函数返回给用户
	ToGoFunction(idx int) GoFunction

	PushGlobalTable()

	GetGlobal(name string) LuaType

	SetGlobal(name string)

	Register(name string, f GoFunction)

	// 类似于PushGoFunction()，也是把Go函数转变成Go闭包推入栈顶
	// 区别在于PushGoClosure()会先从栈顶弹出n个Lua值
	// 这些值会成为Go闭包的Upvalue
	// 留在栈顶的是Go闭包
	PushGoClosure(f GoFunction, n int)


	// 看指定索引处的值是否有元表，如果有，则把元表推入栈顶并返回true
	// 否则栈的状态不改变，返回false
	GetMetatable(idx int) bool

	// 从栈顶弹出一个表
	// 然后把指定索引处值的元表设置成该表
	SetMetatable(idx int)

	// Raw前缀的方法不会去尝试查找调用元方法

	RawLen(idx int) uint

	RawEqual(idx1, idx2 int) bool

	RawGet(idx int) LuaType

	RawSet(idx int)

	RawGetI(idx int, i int64) LuaType

	RawSetI(idx int, i int64)


	// 根据键获取表的下一个键值对
	Next(idx int) bool


	Error() int

	PCall(nArgs, nResults, msgh int) int

	StringToNumber(s string) bool

	// 协程相关
	NewThread() LuaState

	Resume(from LuaState, nArgs int) int

	Yield(nResults int) int

	Status() int

	IsYieldable() bool

	ToThread(idx int) LuaState

	PushThread() bool

	XMove(to LuaState, n int)

	GetStack() bool 	// debug
}